﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Printing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 台签打印
{

    [Serializable]
    public class PrintHandle
    {
        /// <summary>
        /// 默认值 
        /// </summary>
        /// <returns></returns>
        public static PrintHandle Default
        {
            get => new PrintHandle()
            {
                FontName = "楷体",
                MyFontStyle = MyFontStyle.常规,
                FontSizeText = "自动",
                Argb = Color.Black.ToArgb(),
                SizeText = "200*100mm",
                SizeList = new BindingList<string> { "200*100mm", "180*100mm", "150*80mm", "210*100mm",
                    "100*50mm", "134*67mm", "172*86mm", "210*105mm", "210*150mm",
                    "300*105mm-L", "300x210mm-L", "65x45mm", "100x55mm", "210x99mm", "210x145mm" },
                Lines = new[] { "嫦娥", "猪八戒" },
                PrinterName = new PrintDocument().PrinterSettings.PrinterName,
                LineStyle = MyDashStyle.实线,
                InsertBlank = true,
                BorderAlpha = 75,
            };
        }

        //--------UI上排设置项--------
        public string FontName { get; set; }             //字体
        public MyFontStyle MyFontStyle { get; set; }   //字体样式
        public string FontSizeText { get; set; }       //字体选择框文本 
        public float FontemSize { get; set; }           //字体大小
        public int Argb { get; set; }                    //颜色
        public string ImageFile { get; set; }           //背景图片文件
        public string SizeText { get; set; }              //规格尺寸
        public BindingList<string> SizeList { get; set; }  //尺寸列表

        //--------UI内容--------
        public string[] Lines { get; set; }      //文本内容行
        public bool PrintTitle { get; set; }     //标签是否打印标题

        //--------UI下排设置项--------
        public string PrinterName { get; set; }     //打印机名称
        public MyDashStyle LineStyle { get; set; }  //框线
        public bool InsertBlank { get; set; }       //插入空白
        public int BorderAlpha { get; set; }       //边框透明度


        //数据列表
        public string[] ContentList
        {
            get
            {
                var result = Lines.Where(x => !string.IsNullOrWhiteSpace(x)).ToArray();
                //标签打印方式，将第一行作为标题
                if (!PrintTitle) return result;
                //取第一行，分割成数组   //将所有行与与标题行合并，再转换成单行字符串
                var titelArr = result.First().SplitTab();
                //将所有行与与标题行合并，再转换成单行字符串
                return Lines.Skip(1).Select(l => string.Join("\t", titelArr.Zip(l.SplitTab(), (x1, x2) => $"{x1}：{x2}"))).ToArray();
            }
        }

        //配置列表
        public HashSet<Setup> SetupList { get; set; } = new HashSet<Setup>();
        //当前配置
        [NonSerialized] public Setup currentSetup;
        public Setup CurrentSetup
        {
            get
            {
                if (currentSetup?.Text == SizeText) return currentSetup;
                currentSetup = SetupList.FirstOrDefault(x => x.Text == SizeText) ?? Setup.Parse(SizeText);
                if (currentSetup != null)
                {
                    SetupList.Add(currentSetup);
                    if (!SizeList.Contains(SizeText)) SizeList.Add(SizeText);
                }
                return currentSetup;
            }
        }



        //--------打印相关数据--------
        int contentCount;               //页数
        Pen pen1;                    //画笔
        SolidBrush brush1;           //笔刷
        StringFormat stringFormat1;     //文本对齐
        Image image1;               //图片
        RectangleF printableArea;   //打印区域
        List<Rectangle> rectangles;     //页面布局

        public void Print()
        {
            //打印文档
            var printDoc = new PrintDocument()
            {
                DocumentName = "台签打印",
                DefaultPageSettings = { PaperSize = new PaperSize("A4", 827, 1169) },
                PrinterSettings = {
                    Duplex = Duplex.Simplex,  //单面
                    PrinterName = PrinterName,  //打印机名
                },
            };

            //可打印区域大小
            printableArea = printDoc.DefaultPageSettings.PrintableArea;

            //页面大小
            var paperSize = new Size((int)printableArea.Width, (int)printableArea.Height);

            //页面布局
            rectangles = CurrentSetup.GetRectangles(paperSize);
            //页面方向
            printDoc.DefaultPageSettings.Landscape = CurrentSetup.Landscape.Value;

            //边框线画笔
            pen1 = new Pen(Color.FromArgb(BorderAlpha, 0, 0, 0));

            //笔刷 
            brush1 = new SolidBrush(Color.FromArgb(Argb));
            //文本对齐
            stringFormat1 = new StringFormat(StringFormat.GenericTypographic)
            {
                Alignment = StringAlignment.Center,
                LineAlignment = StringAlignment.Center,
            };

            //图片
            image1 = !string.IsNullOrEmpty(ImageFile) && File.Exists(ImageFile) ? Image.FromFile(ImageFile) : null;

            //彩色打印
            printDoc.DefaultPageSettings.Color = brush1.Color != Color.Black || image1 != null
                || CurrentSetup.Title1.Color1 != Color.Black || CurrentSetup.Title2.Color1 != Color.Black;

            //打印事件         
            printDoc.BeginPrint += PrintDoc_BeginPrint;
            printDoc.PrintPage += PrintDocument_PrintPage;

            //打印预览
            var printPreviewDialog = new PrintPreviewDialog
            {
                ClientSize = new Size(428, 498),
                Document = printDoc,
            };
            printPreviewDialog.ShowDialog();
        }

        PrintAction printAction;
        private void PrintDoc_BeginPrint(object sender, PrintEventArgs e)
        {
            printAction = e.PrintAction;
            //页数
            contentCount = ContentList.Length;
            var doc = sender as PrintDocument;
            //Console.WriteLine(doc.DefaultPageSettings);   //PDF-XChange Printer 2012失败
            Console.WriteLine(doc.PrinterSettings);
            Console.WriteLine(doc.DefaultPageSettings.PrintableArea);
        }

        private void PrintDocument_PrintPage(object sender, PrintPageEventArgs e)
        {
            Graphics grfx = e.Graphics;
            grfx.PageUnit = GraphicsUnit.Display;  //单位 1/100英寸  

            if (printAction == PrintAction.PrintToPreview)
                grfx.TranslateTransform(printableArea.X, printableArea.Y);  //坐标原点平移
            var edges = RectangleEdges.GetEdges(rectangles).ToList();  //全部边线

            var lines = ContentList;
            Console.WriteLine("contentIndex=" + contentCount); //页数
            foreach (var rect in rectangles)
            {
                //文本内容   
                var text = contentCount > 0 ? lines[lines.Length - contentCount] : string.Empty;
                if (CurrentSetup.Mirror)
                {
                    //矩形一分二，上下镜像绘制
                    var state = grfx.Save();
                    grfx.TranslateTransform(rect.X, rect.Y);  //坐标原点移到左上角
                    var rect2 = new Rectangle(0, rect.Height / 2, rect.Width, rect.Height / 2); //下半部分
                    DrawContent(grfx, rect2, text);     //绘制文字
                    var point1 = rect.Location + (Size)rect2.Location;
                    edges.Add(new RectangleEdges.Edge(point1, point1 + new Size(rect2.Width, 0))); //中线
                    grfx.TranslateTransform(rect.Width, rect.Height);  //坐标原点移到右下角
                    grfx.RotateTransform(180);  //旋转
                    DrawContent(grfx, rect2, text);     //绘制文字
                    grfx.Restore(state);
                }
                else
                {
                    //矩形内绘制主体内容
                    DrawContent(grfx, rect, text);   //绘制文字
                }
                contentCount--;
            }

            //绘制边线
            foreach (var edge in edges)
            {
                //边框线样式
                switch (LineStyle)
                {
                    case MyDashStyle.实线:
                        pen1.DashStyle = DashStyle.Solid;
                        goto default;
                    case MyDashStyle.虚线:
                        pen1.DashStyle = DashStyle.Dash;
                        goto default;
                    case MyDashStyle.点:
                        pen1.DashStyle = DashStyle.Dot;
                        goto default;
                    case MyDashStyle.角:
                        grfx.DrawCrossMark(pen1, edge.Start);   //绘制十字标记
                        grfx.DrawCrossMark(pen1, edge.End);
                        break;
                    case MyDashStyle.无:
                        break;
                    default:
                        grfx.DrawLine(pen1, edge.Start, edge.End);  //绘制线条
                        break;
                }
            }

            //页面控制
            e.HasMorePages = contentCount > 0;
        }

        /// <summary>
        /// 矩形内绘制主体文本
        /// </summary>
        private void DrawContent(Graphics grfx, Rectangle rect, string text)
        {
            if (string.IsNullOrWhiteSpace(text)) return;
            if (ImageFile != null) grfx.DrawImage(image1, rect);    //绘制背景图片
            text = text.NewLine();      //处理换行
            text = DrawTitleText(grfx, rect, text, CurrentSetup.Title1);  //抬头
            text = DrawTitleText(grfx, rect, text, CurrentSetup.Title2); //落款
            var font2 = new Font(FontName, FontemSize, (FontStyle)MyFontStyle);     //字体
            font2 = FontHandle.Get(grfx, rect.Size, font2, text, CurrentSetup.MarginRatio);    //字体大小调整
            rect.Offset(CurrentSetup.Offset);   //XY偏移                                     
            if (InsertBlank)
            {
                grfx.DrawDistributedString(text, font2, brush1, rect, CurrentSetup.MarginRatio);  //绘制分散对齐字符串 
            }
            else
            {
                grfx.DrawString(text, font2, brush1, rect, stringFormat1);  //绘制字符串         
            }
            font2.Dispose();
        }

        /// <summary>
        /// 绘制抬头 落款
        /// </summary>
        private string DrawTitleText(Graphics grfx, Rectangle rect, string text, Title title)
        {
            var content = title.Content;
            if (title.Enabled && !string.IsNullOrWhiteSpace(content))
            {
                if (content == "第一列" || content == "最后一列")
                {
                    var arrs = text.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
                    {
                        if (content == "第一列")
                        {
                            content = arrs.First();
                            text = string.Join(Environment.NewLine, arrs.Skip(1));
                        }
                        else if (content == "最后一列")
                        {
                            content = arrs.Last();
                            text = string.Join(Environment.NewLine, arrs.Take(arrs.Length - 1));
                        }
                    }
                }
                var brush2 = new SolidBrush(title.Color1);
                var point = rect.Location + (Size)title.Point.Millimeter2Inch();
                grfx.DrawString(content, title.Font1, brush2, point);
            }
            return text;
        }

    }

    [TypeConverter(typeof(EnumConverter))]
    public enum MyDashStyle
    {
        实线, 虚线, 点, 角, 无
    }
}
